/* This thread listens for incomming connections.
 * It creates a ConnHandler for every new connection.
 */

package org.kth.dks.dks_comm;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Enumeration;
import java.util.Vector;

import org.kth.dks.dks_marshal.DKSMarshal;
import org.kth.dks.dks_marshal.MsgSrcDestWrapper;

/**
 * <p>Title: DKS</p>
 * <p>Description: DKS Middleware</p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: KTH-IMIT</p>
 * @author Ali Ghodsi (aligh@kth.se)
 * @version 1.0
 */

class ListenerBlocking extends Thread implements Listener {

  private static final int BACKLOG = 20;
  private int port = 0;
    private boolean finish = false;
    private Vector connList = new Vector();
    private ConnectionManager a_conMan;
    private final ServerSocket serverSocket;
    private final ConnectionHandler connHandler;

    private int statisticsBytesReceived            = 0;
    private int statisticsMsgsReceived             = 0;

    //new
    public DKSMarshal dksMarshal = null;

    public ListenerBlocking( int _port, ConnectionManager cm, DKSMarshal dksm, ConnectionHandler ch ) throws IOException
    {
      this.port = _port;
      this.connHandler = ch;
      dksMarshal = dksm;
      a_conMan = cm;
      serverSocket = new ServerSocket(port);
      serverSocket.setSoTimeout(1000);
      this.setName(ListenerBlocking.class.getName());
      this.start();
    }

    public ListenerBlocking( int _port, ConnectionManager cm, DKSMarshal dksm, ConnectionHandler ch, InetAddress bindAddr ) throws IOException
    {
      this.port = _port;
      this.connHandler = ch;
      dksMarshal = dksm;
      a_conMan = cm;
      serverSocket = new ServerSocket(port, BACKLOG, bindAddr);
      serverSocket.setSoTimeout(1000);
      this.setName(ListenerBlocking.class.getName());
      this.start();
    }

    public void end() {
    	finish = true;
    }

  public void run() {

    while ( !finish ) {
      try {
        Socket socket = null;
        socket = serverSocket.accept();
        if( socket != null ) {

          InetSocketAddress sa = (InetSocketAddress) socket.getRemoteSocketAddress();
          DKSNetAddress na = new DKSNetAddress(sa.getAddress().getHostAddress(), sa.getPort());
          connHandler.createConnection(socket, na);
        }
      }
      catch (SocketTimeoutException ste ) {
      }
      catch (Exception ex1) {
        ex1.printStackTrace();
      }
    }


    while( ! connList.isEmpty() ) {
      ConnHandlerIn h = (ConnHandlerIn)connList.elementAt(0);
      h.end();
      connList.removeElementAt(0);
    }
  } //run

	public boolean send(MsgSrcDestWrapper triple) {
		return connHandler.send(triple);
	}

	
	public int getLocalPort() {
      return serverSocket.getLocalPort();
    }

    public String getHostAddress() {
    	byte[] ip = serverSocket.getInetAddress().getAddress();
    	if (ip[0]==0 && ip[1]==0 && ip[2]==0 && ip[3]==0) {
    	    String currIp = null;
    		try
    	      {
    	    	Enumeration cards = NetworkInterface.getNetworkInterfaces();
    	    	while (cards.hasMoreElements()) {
    	    		NetworkInterface currNet = (NetworkInterface)cards.nextElement(); 
    	    		Enumeration ads = currNet.getInetAddresses();
    	    		while (ads.hasMoreElements()) {
    	    			InetAddress adr = (InetAddress) ads.nextElement();
    	    			String c = adr.getHostAddress();
                        if (adr instanceof Inet4Address && !c.equals("127.0.0.1") && 
                        		!c.startsWith("169.") &&
                        		!c.startsWith("10.") &&
                        		!c.startsWith("192.")) 
                            currIp=c;
    	    		}
    	    	}
    	    	if (currIp==null) {
    	    		InetAddress ia =  InetAddress.getLocalHost();
    	    		currIp = ia.getHostAddress();
    	    	}
    	        return currIp;
    	      } catch (Exception ex) { ex.printStackTrace(); }

    	} else {
    		return serverSocket.getInetAddress().getHostAddress();
    	}

      return null;
    }

} //Listener class
